home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
363_01
/
miscel.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-15
|
30KB
|
958 lines
/***********************************************************************
*
* MISCEL - Routines for 68020 Assembler
* Routines for instructions:
* BKPT, CALLM,
*
* All functions accept the same parameters:
*
* tablePtr - pointer to the instruction table,
* size - not used. Included for compatibility with the opDescriptor
* struct definition.
* label - pointer to the label string, empty string if no label
* op - pointer to the input string,
* errorPtr - pointer to the error flag.
*
* and return integer flag.
*
* The functions return an error code in *errorPtr using the standard
* mechanism.
*
*
* Author: Andrew E. Romer. Version 1.0
* 38 Bolsover Road, Worthing, West Sussex, England BN13 1NT.
*
* Date: May 1991
*
***********************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "asm.h"
extern long loc;
extern char pass2;
/***********************************************************************
*
* Function bkPoint builds the instruction
* BKPT #<data>
*
***********************************************************************/
#define BKPT_MASK 0x4848
int bkPoint(instruction *tablePtr, int size, char *label, char *op,
int *errorPtr)
{
opDescriptor source;
/* op points to the first character of the operand field */
/* Move location counter to a word boundary and fix the listing before
* assembling the instruction */
if (loc & 1) /* if not at word boundary */
{
loc++;
listLoc();
}
if (*label)
{
create(label, loc, errorPtr);
if (*errorPtr > SEVERE)
return NORMAL;
}
if (size)
NEWERROR(*errorPtr, UNSIZED);
op = opParse(op, &source, errorPtr);
if (*errorPtr > SEVERE)
return NORMAL;
if (source.mode != Immediate)
{
NEWERROR(*errorPtr, INV_ADDR_MODE);
return NULL;
}
if (!isspace(*op) && *op != '\0')
/* if operand field contains
* superfluous characters */
{
NEWERROR(*errorPtr, SYNTAX);
return NORMAL;
}
if (pass2)
{
output( (long) (BKPT_MASK | (source.data & 0x7)), WORD);
if (source.data < 0 || source.data > 7)
NEWERROR(*errorPtr, INV_3_BIT_DATA);
}
loc += 2;
}
/***********************************************************************
*
* Function callModule builds the instruction
* CALLM #<data>,<ea>
*
***********************************************************************/
#define CALLM_MASK 0x06c0
int callModule(instruction *tablePtr, int size, char *label, char *op,
int *errorPtr)
{
opDescriptor source, dest;
/* op points to the first character of the operand field */
/* Move location counter to a word boundary and fix the listing before
* assembling the instruction */
if (loc & 1) /* if not at word boundary */
{
loc++;
listLoc();
}
if (*label)
{
create(label, loc, errorPtr);
if (*errorPtr > SEVERE)
return NORMAL;
}
if (size)
NEWERROR(*errorPtr, UNSIZED);
op = opParse(op, &source, errorPtr); /* parse source */
if (*errorPtr > SEVERE)
return NORMAL;
if (source.mode != Immediate)
{
NEWERROR(*errorPtr, INV_ADDR_MODE);
return NULL;
}
if (*op != ',') /* missing source/destination separator */
{
NEWERROR(*errorPtr, SYNTAX);
return NORMAL;
}
op = opParse(op+1, &dest, errorPtr);
if (*errorPtr > SEVERE)
return NORMAL;
if ((dest.mode & Control) == 0)
{
NEWERROR(*errorPtr, INV_ADDR_MODE);
return NULL;
}
if (!isspace(*op) && *op != '\0')
/* if operand field contains
* superfluous characters */
{
NEWERROR(*errorPtr, SYNTAX);
return NORMAL;
}
if (pass2)
output( (long) (CALLM_MASK | effAddr(&dest)), WORD);
loc += 2;
if (pass2)
{
output( (long) (source.data & 0xff), WORD);
if (source.data < 0 || source.data > 255)
NEWERROR(*errorPtr, INV_8_BIT_DATA);
}
loc += 2;
extWords(&dest, size, errorPtr);
return NORMAL;
}
/***********************************************************************
*
* Function comSwap builds the instruction
* CAS Dc,Du,<ea>
*
***********************************************************************/
#define isRegNum(c) ((c >= '0') && (c <= '7'))
#define CAS_BYTEMASK 0x0ac0
#define CAS_WORDMASK 0x0cc0
#define CAS_LONGMASK 0x0ec0
int compSwap(instruction *tablePtr, int size, char *label, char *op,
int *errorPtr)
{
opDescriptor source;
char regc, regu;
/* op points to the first character of the operand field */
/* Move location counter to a word boundary and fix the listing before
* assembling the instruction */
if (loc & 1) /* if not at word boundary */
{
loc++;
listLoc();
}
if (*label)
{
create(label, loc, errorPtr);
if (*errorPtr > SEVERE)
return NORMAL;
}
/* Parse Dc and Du */
if (op[0] == 'D' && isRegNum(op[1]) && op[2] == ',' && op[3] == 'D'
&& isRegNum(op[4]) && op[5] == ',')
{
regc = op[1] - '0';
regu = op[4] - '0';
}
else
{
NEWERROR(*errorPtr, SYNTAX);
return NORMAL;
}
/* Parse effective address */
op = opParse(op+6, &source, errorPtr);
if (*errorPtr > SEVERE)
return NORMAL;
if ((source.mode & MemAlt) == 0)
{
NEWERROR(*errorPtr, INV_ADDR_MODE);
return NULL;
}
if (!isspace(*op) && *op != '\0')
/* if operand field contains
* superfluous characters */
{
NEWERROR(*errorPtr, SYNTAX);
return NORMAL;
}
/* generate output */
if (pass2)
switch (size)
{
case BYTE:
output( (long) (CAS_BYTEMASK | effAddr(&source)), WORD);
break;
case LONG:
output( (long) (CAS_LONGMASK | effAddr(&source)), WORD);
break;
default: /* size == WORD || size == 0 */
output( (long) (CAS_WORDMASK | effAddr(&source)), WORD);
break;
}
loc += 2;
if (pass2)
output( (long) ((regu << 6) | regc), WORD);
loc += 2;
extWords(&source, size, errorPtr);
return NORMAL;
}
/***********************************************************************
*
* Function comSwap2 builds the instruction
* CAS2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2)
*
***********************************************************************/
#define CAS2_WORDMASK 0x0cfc
#define CAS2_LONGMASK 0x0efc
int compSwap2(instruction *tablePtr, int size, char *label, char *op,
int *errorPtr)
{
opDescriptor source, dest;
char regc1, regc2, regu1, regu2, regn1, regn2;
/* op points to the first character of the operand field */
/* Move location counter to a word boundary and fix the listing before
* assembling the instruction */
if (loc & 1) /* i